package factory.one.service;

import factory.one.entity.Order;
import factory.one.pojo.common.SqlCondition;
import factory.one.utils.SqlUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.sql.*;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author sk.z
 * 2023/6/26
 * 订单
 **/
@Service
public class OrderService {

    private final JdbcTemplate jdbcTemplate;
    private final OrderSequenceService sequenceService;

    public OrderService(JdbcTemplate jdbcTemplate, OrderSequenceService sequenceService) {
        this.jdbcTemplate = jdbcTemplate;
        this.sequenceService = sequenceService;
    }

    private static final DateTimeFormatter CODE = DateTimeFormatter.ofPattern("yyMMddHHmmss");

    public Long add(Order order) {
        PreparedStatementCreator preparedStatementCreator = con -> {
            PreparedStatement statement = con.prepareStatement(
                    "insert into \"ORDER\"(code,custom_id,order_num,contract_amount,create_user,create_time) values(?,?,?,?,?,?)",
                    Statement.RETURN_GENERATED_KEYS);
            statement.setString(1, sequenceService.nextCode());
            statement.setLong(2, order.getCustomId());
            statement.setInt(3, order.getOrderNum());
            statement.setLong(4, order.getContractAmount());
            statement.setString(5, order.getCreateUser());
            statement.setTimestamp(6, new Timestamp(System.currentTimeMillis()));
            return statement;
        };
        GeneratedKeyHolder holder = new GeneratedKeyHolder();
        jdbcTemplate.update(preparedStatementCreator, holder);
        return holder.getKey() == null ? null : holder.getKey().longValue();
    }

    public int update(Order order) {
        return jdbcTemplate.update("update \"ORDER\" set custom_id=?, contract_amount=?, order_num=? where id=? ", ps -> {
            ps.setLong(1, order.getCustomId());
            ps.setLong(2, order.getContractAmount());
            ps.setInt(3, order.getOrderNum());
            ps.setLong(4, order.getId());
        });
    }

    public int updateNumber(Long orderId, Integer produce, Integer send, Integer refund) {
        return jdbcTemplate.update("update \"ORDER\" set produce_num = ?, send_num = ?, refund_num = ? where id=? ", ps -> {
            ps.setInt(1, produce);
            ps.setInt(2, send);
            ps.setInt(3, refund);
            ps.setLong(4, orderId);
        });
    }

    public int updateSendNumber(Long orderId, Integer send) {
        return jdbcTemplate.update("update \"ORDER\" set send_num = ? where id=? ", ps -> {
            ps.setInt(1, send);
            ps.setLong(2, orderId);
        });
    }

    public int updateAmount(Long orderId, Long actualAmount) {
        return jdbcTemplate.update("update \"ORDER\" set actual_amount = ? where id=? ", ps -> {
            ps.setLong(1, actualAmount);
            ps.setLong(2, orderId);
        });
    }

    public int updateConfirm(Long orderId, boolean confirm) {
        return jdbcTemplate.update("update \"ORDER\" set is_confirm=? where id=? ", confirm, orderId);
    }

    public int del(Long orderId) {
        return jdbcTemplate.update("update \"ORDER\" set status=0 where id=? ", orderId);
    }

    public int resume(Long orderId) {
        return jdbcTemplate.update("update \"ORDER\" set status=1 where id=? ", orderId);
    }

    public List<Order> list(int page, int size) {
        return jdbcTemplate.query("select * from \"ORDER\" order by id desc " + SqlUtil.page(page, size), new OrderRowMapper());
    }

    public Integer listCount() {
        return jdbcTemplate.queryForObject("select count(*) from \"ORDER\" ", Integer.class);
    }

    public List<Order> listByCondition(int page, int size, List<SqlCondition> conditions) {
        StringBuilder sql = new StringBuilder("select * from \"ORDER\" where 1=1 ");
        if (CollectionUtils.isEmpty(conditions)) {
            sql.append("order by id desc ").append(SqlUtil.page(page, size));
            return jdbcTemplate.query(sql.toString(), new OrderRowMapper());
        }

        Object[] args = new Object[conditions.size()];
        int[] types = new int[conditions.size()];
        for (int i = 0; i < conditions.size(); i++) {
            SqlCondition condition = conditions.get(i);
            sql.append("AND ").append(condition.getSqlDesc()).append(" ");
            args[i] = condition.getValue();
            types[i] = condition.getValueType();
        }
        sql.append("order by id desc ").append(SqlUtil.page(page, size));
        return jdbcTemplate.query(sql.toString(), args, types, new OrderRowMapper());
    }

    public Integer countByCondition(List<SqlCondition> conditions) {
        StringBuilder sql = new StringBuilder("select count(*) from \"ORDER\" where 1=1 ");
        if (CollectionUtils.isEmpty(conditions)) {
            return jdbcTemplate.queryForObject(sql.toString(), Integer.class);
        }

        Object[] args = new Object[conditions.size()];
        int[] types = new int[conditions.size()];
        for (int i = 0; i < conditions.size(); i++) {
            SqlCondition condition = conditions.get(i);
            sql.append("AND ").append(condition.getSqlDesc()).append(" ");
            args[i] = condition.getValue();
            types[i] = condition.getValueType();
        }
        return jdbcTemplate.queryForObject(sql.toString(), args, types, Integer.class);
    }

    public Order getById(Long id) {
        return jdbcTemplate.queryForObject("select * from \"ORDER\" where id = " + id, new OrderRowMapper());
    }

    private static class OrderRowMapper implements RowMapper<Order> {
        @Override
        public Order mapRow(ResultSet rs, int rowNum) throws SQLException {
            Order order = new Order();
            order.setId(rs.getLong("id"));
            order.setCode(rs.getString("code"));
            order.setCustomId(rs.getLong("custom_id"));
            order.setContractAmount(rs.getLong("contract_amount"));
            order.setActualAmount(rs.getLong("actual_amount"));
            order.setOrderNum(rs.getInt("order_num"));
            order.setProduceNum(rs.getInt("produce_num"));
            order.setSendNum(rs.getInt("send_num"));
            order.setRefundNum(rs.getInt("refund_num"));
            order.setConfirm(rs.getBoolean("is_confirm"));
            order.setCreateUser(rs.getString("create_user"));
            order.setCreateTime(rs.getTimestamp("create_time"));
            order.setStatus(rs.getInt("status"));
            return order;
        }
    }

}
